#include "X86_Machine.h"
#include "allocator.h"

X86_Machine* X86_Machine::_instance = 0;
char X86_MachineStub[sizeof(X86_Machine) + StaticAllocator::StubSize];
IMPLEMENT_SUPPORT_ALLOCATOR(X86_Machine)

X86_Machine::X86_Machine(void)
{
}

X86_Machine::~X86_Machine(void)
{
}

X86_Machine* X86_Machine::Instance()
{
	if(!_instance)
		_instance = new(&StaticAllocator(X86_MachineStub, sizeof(X86_MachineStub))) X86_Machine;
	return _instance;
}

void X86_Machine::GetIdt( PIDT pIdt )
{
	__asm{
		mov eax, pIdt
		sidt [eax]
	}
}

void X86_Machine::SetDebugRegister( unsigned DrX, UINT32 v)
{
	switch (DrX)
	{
	case OPCODE_DR0:
		SetDr0(v);
		break;
	case OPCODE_DR1:
		SetDr1(v);
		break;
	case OPCODE_DR2:
		SetDr2(v);
		break;
	case OPCODE_DR3:
		SetDr3(v);
		break;
	case OPCODE_DR4:
		SetDr4(v);
		break;
	case OPCODE_DR5:
		SetDr5(v);
		break;
	case OPCODE_DR6:
		SetDr6(v);
		break;
	case OPCODE_DR7:
		SetDr7(v);
		break;
	default:
		DbgBreakPoint();
	}
}

void X86_Machine::SetDr0( UINT32 v )
{
	__asm
	{
		mov eax,v
		mov dr0,eax
	}
}
void X86_Machine::SetDr1( UINT32 v )
{
	__asm
	{
		mov eax,v
		mov dr1,eax
	}
}
void X86_Machine::SetDr2( UINT32 v )
{
	__asm
	{
		mov eax,v
		mov dr2,eax
	}
}
void X86_Machine::SetDr3( UINT32 v )
{
	__asm
	{
		mov eax,v
		mov dr3,eax
	}
}
void X86_Machine::SetDr4( UINT32 v )
{
	DbgBreakPoint();
	__asm
	{
		//mov eax,v
		//mov dr4,eax
	}
}
void X86_Machine::SetDr5( UINT32 v )
{
	DbgBreakPoint();
	__asm
	{
		//mov eax,v
		//mov dr5,eax
	}
}
void X86_Machine::SetDr6( UINT32 v )
{
	__asm
	{
		mov eax,v
		mov dr6,eax
	}
}
void X86_Machine::SetDr7( UINT32 v )
{
	__asm
	{
		mov eax,v
		mov dr7,eax
	}
}

UINT32 X86_Machine::GetDebugRegister( unsigned DrX )
{
	typedef UINT32 (*GetDrX)(void);
	static GetDrX DrXRoutine[8] = {GetDr0, GetDr1, GetDr2, GetDr3, GetDr4, GetDr5, GetDr6, GetDr7};
	if(DrX > 7)
		DbgBreakPoint();
	return DrXRoutine[DrX]();
}

UINT32 X86_Machine::GetDr0()
{
	UINT32 v;
	__asm
	{
		mov eax,dr0
		mov v,eax
	}
	return v;
}
UINT32 X86_Machine::GetDr1()
{
	UINT32 v;
	__asm
	{
		mov eax,dr1
		mov v,eax
	}
	return v;
}
UINT32 X86_Machine::GetDr2()
{
	UINT32 v;
	__asm
	{
		mov eax,dr2
		mov v,eax
	}
	return v;
}
UINT32 X86_Machine::GetDr3()
{
	UINT32 v;
	__asm
	{
		mov eax,dr3
		mov v,eax
	}
	return v;
}
UINT32 X86_Machine::GetDr4()
{
	UINT32 v;
	DbgBreakPoint();
	__asm
	{
		//mov eax,dr4
		//mov v,eax
	}
	return 0;
}
UINT32 X86_Machine::GetDr5()
{
	UINT32 v;
	DbgBreakPoint();
	__asm
	{
		//mov eax,dr5
		//mov v,eax
	}
	return 0;
}
UINT32 X86_Machine::GetDr6()
{
	UINT32 v;
	__asm
	{
		mov eax,dr6
		mov v,eax
	}
	return v;
}
UINT32 X86_Machine::GetDr7()
{
	UINT32 v;
	__asm
	{
		mov eax,dr7
		mov v,eax
	}
	return v;
}